# -*- coding: UTF-8 -*-
import logging
import queue
import time
import os
import json
import sqlite3
import paho.mqtt.client as mqtt
import threading
from concurrent.futures import ThreadPoolExecutor
from tools.logger import log # 导入封装的logger方法


# 自定义模块
import send_hello
import GetDeviceBaseInfo_send
from Mqtt.volumes import thread_post
from mysqltest.mysql_db import sqlconnect

# ========== 全局配置 ==========
MQTT_SERVER = "172.16.1.29"
MQTT_PORT = 18832
MQTT_USERNAME = "intranet"
MQTT_PASSWORD = "gst@2024_123!"
MQTT_TOPIC = "IOT/intranet/client/request/prod/+"
MQTT_PUBLISH_TOPIC = "IOT/intranet/server/report/prod/"

# 共享队列
param_queue = queue.Queue()
param_queue1 = queue.Queue()
param_queue2 = queue.Queue()
param_queue3 = queue.Queue()



# ========== 设备操作类 ==========
class ThreadPost:
  def __init__(self):
    self.operation_lock = threading.Lock()
    self.operations_completed = False
    self.current_operation = None  # 跟踪当前正在执行的操作

  def initialize(self):
    """初始化资源，每个周期开始时调用"""
    log.info("初始化设备操作资源")
    self.operations_completed = False
    self.current_operation = None

  def cleanup(self):
    """清理资源，每个周期结束时调用"""
    log.info("清理设备操作资源")
    # 在这里添加资源清理逻辑，例如：
    # thread_post.reset_state()  # 如果 thread_post 有重置方法

  def audiostop_post(self):
    with self.operation_lock:
      if self.operations_completed or self.current_operation == "audiostop":
        log.warning("音频停止操作已完成或正在执行，跳过重复执行")
        return
      self.current_operation = "audiostop"
      log.info("执行音频停止操作")
      thread_post.audiostop_post()  # 实际操作

  def relay_post(self):
    with self.operation_lock:
      if self.operations_completed or self.current_operation == "relay":
        log.warning("继电器操作已完成或正在执行，跳过重复执行")
        return
      self.current_operation = "relay"
      log.info("执行继电器操作")
      thread_post.relay_post()  # 实际操作

  def volume_post(self):
    with self.operation_lock:
      if self.operations_completed or self.current_operation == "volume":
        log.warning("音量调节操作已完成或正在执行，跳过重复执行")
        return
      self.current_operation = "volume"
      log.info("执行音量调节操作")
      thread_post.volume_post()  # 实际操作

  def mark_operations_completed(self):
    """标记所有操作已完成"""
    """标记所有操作已完成"""
    with self.operation_lock:
      self.operations_completed = True
      self.current_operation = None


# ========== MQTT 控制器 ==========
class MQTTController:
  def __init__(self):
    self.keep_running = True
    self.client = mqtt.Client()
    self.callback_thread = None
    self.timers = {}

    # MQTT 客户端初始化
    self.client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
    self.client.on_connect = self.on_connect
    self.client.on_message = self.on_message

  def on_connect(self, client, userdata, flags, rc):
    if rc == 0:
      log.info("成功连接到MQTT代理！")
      client.subscribe(MQTT_TOPIC)
    else:
      log.error(f"连接失败，错误码：{rc}")

  def on_message(self, client, userdata, message):
    try:
      msg = json.loads(message.payload.decode())
      log.info(f"收到消息: {msg} from {message.topic}")

      # 队列投递
      param_queue.put(message.topic)
      param_queue1.put(msg.get('publishId'))
      param_queue2.put(msg.get('imei'))
      param_queue3.put(msg.get('cmd'))

    except Exception as e:
      log.error(f"消息处理错误: {str(e)}")

  def _callback_loop(self):
    while self.keep_running:
      try:
        # 从队列取数据并响应 MQTT
        data = {
          'param': param_queue.get(timeout=1),
          'publishid': param_queue1.get(timeout=1),
          'imei': param_queue2.get(timeout=1),
          'cmd': param_queue3.get(timeout=1)
        }
        pub_topic = f"{MQTT_PUBLISH_TOPIC}{data['imei']}"
        response = {
          "cmd": data['cmd'],
          "imei": data['imei'],
          "publishId": data['publishid'],
          "result": "success",
          "resultId": 1,
          "topic": data['param']
        }
        self.client.publish(pub_topic, json.dumps(response))
        log.info(f"即时响应: {response}")

      except queue.Empty:
        continue
      except Exception as e:
        log.error(f"队列处理错误: {str(e)}")

  def start(self):
    """启动 MQTT 连接和回调线程"""
    self.client.connect(MQTT_SERVER, MQTT_PORT, 60)
    self.client.loop_start()

    self.callback_thread = threading.Thread(
      target=self._callback_loop,
      daemon=True
    )
    self.callback_thread.start()

  def stop(self):
    """停止 MQTT 相关资源"""
    self.keep_running = False
    for timer in self.timers.values():
      if timer and timer.is_alive():
        timer.cancel()
    if self.callback_thread and self.callback_thread.is_alive():
      self.callback_thread.join(timeout=2)
    self.client.loop_stop()
    self.client.disconnect()
    log.info("MQTT 服务已安全停止")


# ========== 业务操作函数 ==========
def run_operations(thread_post, operation_complete_event):
  """执行一次完整的业务操作序列，确保所有操作按顺序完成"""
  try:
    thread_post.initialize()  # 初始化操作资源

    operations = [
      ("音频停止", thread_post.audiostop_post),
      ("继电器操作", thread_post.relay_post),
      ("音量调节", thread_post.volume_post)
    ]

    for name, operation in operations:
      log.info(f"开始执行: {name}")
      operation()
      # 添加短暂延迟确保操作完成
      time.sleep(1)
      log.info(f"完成: {name}")

    thread_post.mark_operations_completed()  # 标记操作完成
    operation_complete_event.set()  # 通知主程序操作已完成

  except Exception as e:
    log.error(f"业务操作序列执行失败: {str(e)}")
    raise
  finally:
    thread_post.cleanup()  # 清理操作资源


def set_runStatus():
  """更新设备运行状态"""
  try:
    sql = "update device set run_status = 1 where device_name between 1 and 20"
    sqlconnect.sqljudje(sql)
    sql1 = "select run_status from device where device_name = 20"
    result = sqlconnect.sqljudje(sql1)
    log.info(f"当前设备在线状态：{result[0][0]}")
    if result[0][0] == 1:
      log.info("mock对象状态已更新为：在线")
  except Exception as e:
    log.error(f"更新设备状态失败: {str(e)}")
    raise

def main():
  # 初始化 MQTT 控制器（全程复用）
  controller = MQTTController()
  controller.start()

  # 初始化设备操作类
  thread_post = ThreadPost()

  # 启动独立线程（心跳、基础信息上报）
  log.info("独立线程-1: 心跳信息，已启动")
  thread_hello = threading.Thread(
    target=send_hello.hello,
    daemon=True
  )
  thread_hello.start()

  log.info("独立线程-2: GetDeviceBaseInfo 信息，已启动")
  thread_baseinfo = threading.Thread(
    target=GetDeviceBaseInfo_send.main,
    daemon=True
  )
  thread_baseinfo.start()

  try:
    while True:
      cycle_start_time = time.time()
      log.info("============ 新周期开始 ============")

      try:
        # 创建事件用于等待操作完成
        operation_complete_event = threading.Event()
        operation_complete_event.clear()

        # 更新设备状态
        set_runStatus()
        # 确保没有未完成的操作
        if not operation_complete_event.is_set():
          run_operations(thread_post, operation_complete_event)
        else:
          log.warning("上一周期操作未完成，跳过本次执行")


      except Exception as e:
        log.error(f"周期执行异常: {str(e)}", exc_info=True)


      log.info("============ 周期结束 ============\n")
      time.sleep(2)

  except KeyboardInterrupt:
    log.info("主进程被强制终止")
  finally:
    # 停止 MQTT 服务
    controller.stop()
    log.info("主进程退出")

if __name__ == "__main__":
  try:
    log.info("启动 MQTT 服务...")
    main()
    log.info("程序正常退出")
  except Exception as e:
    log.error(f"程序运行出错: {str(e)}", exc_info=True)